/*
 * RISC-V相关定义
 * 包含页表项格式、权限位定义、地址操作宏等
 */

#ifndef RISCV_H
#define RISCV_H

#include <stdint.h>

#ifndef __ASSEMBLER__

// 页表项类型定义
typedef uint64_t pte_t;
typedef uint64_t *pagetable_t; // 512个PTE的页表

// SATP寄存器操作
#define SATP_SV39 (8L << 60)
#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64_t)pagetable) >> 12))

// 读写SATP寄存器
static inline void w_satp(uint64_t x)
{
    asm volatile("csrw satp, %0" : : "r" (x));
}

static inline uint64_t r_satp()
{
    uint64_t x;
    asm volatile("csrr %0, satp" : "=r" (x));
    return x;
}

// 刷新TLB
static inline void sfence_vma()
{
    // 刷新所有TLB条目
    asm volatile("sfence.vma zero, zero");
}

#endif // __ASSEMBLER__

// 页面大小相关定义
#define PGSIZE 4096 // 每页字节数
#define PGSHIFT 12  // 页内偏移位数

// 地址对齐宏
#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1))
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))

// 页表项标志位定义
#define PTE_V (1L << 0) // 有效位
#define PTE_R (1L << 1) // 读权限
#define PTE_W (1L << 2) // 写权限
#define PTE_X (1L << 3) // 执行权限
#define PTE_U (1L << 4) // 用户态可访问

// 物理地址和页表项之间的转换
#define PA2PTE(pa) ((((uint64_t)pa) >> 12) << 10)
#define PTE2PA(pte) (((pte) >> 10) << 12)
#define PTE_FLAGS(pte) ((pte) & 0x3FF)

// 从虚拟地址提取页表索引
#define PXMASK          0x1FF // 9位掩码
#define PXSHIFT(level)  (PGSHIFT+(9*(level)))
#define PX(level, va) ((((uint64_t) (va)) >> PXSHIFT(level)) & PXMASK)

// Sv39虚拟地址空间最大值
// 实际比Sv39允许的最大值小1位，避免符号扩展问题
#define MAXVA (1L << (9 + 9 + 9 + 12 - 1))

// VPN提取宏（用于地址解析）
#define VPN_SHIFT(level) (12 + 9 * (level))
#define VPN_MASK(va, level) (((va) >> VPN_SHIFT(level)) & 0x1FF)

#endif // RISCV_H